package com.qiguliuxing.dts.core.express;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qiguliuxing.dts.core.express.config.ExpressProperties;
import com.qiguliuxing.dts.core.express.dao.ExpressInfoV1;
import com.qiguliuxing.dts.core.util.HttpUtil;
import org.springframework.util.Base64Utils;

import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 物流查询服务
 * <p>
 * 快递鸟即时查询API http://www.kdniao.com/api-track
 */
public class ExpressService {
    // 请求url
    private String ReqURL = "http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";

    private ExpressProperties properties;

    public ExpressProperties getProperties() {
        return properties;
    }

    public void setProperties(ExpressProperties properties) {
        this.properties = properties;
    }

    /**
     * 获取所有物流供应商信息
     *
     * @param vendorCode
     * @return
     */
    public List<Map<String, String>> getAllVendor() {
        return properties.getVendors();
    }

    /**
     * 获取物流供应商名
     *
     * @param vendorCode
     * @return
     */
    public String getVendorName(String vendorCode) {
        for (Map<String, String> item : properties.getVendors()) {
            if (item.get("code").equals(vendorCode))
                return item.get("name");
        }
        return null;
    }

    /**
     * 获取物流信息
     *
     * @param expCode
     * @param expNo
     * @return
     */
    public ExpressInfoV1 getExpressInfo(String expCode, String expNo) {
        try {
            String result = getOrderTracesByJson(expCode, expNo);
            ObjectMapper objMap = new ObjectMapper();
            ExpressInfoV1 ei = objMap.readValue(result, ExpressInfoV1.class);
            // 对物流按时间进行倒序排列
            if (ei != null && ei.getTraces() != null && ei.getTraces().size() > 0) {
                ei.getTraces().sort((m1, m2) -> m2.getAcceptTime().compareTo(m1.getAcceptTime()));
            }
            ei.setShipperName(getVendorName(expCode));
            return ei;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String result = "{  \"StateEx\" : \"2\",  \"LogisticCode\" : \"YT2098143390812\",  \"ShipperCode\" : \"YTO\",  \"Traces\" : [ {    \"Action\" : \"1\",    \"AcceptStation\" : \"【江苏省无锡市锡新开发区公司】 已收入\",    \"AcceptTime\" : \"2020-11-01 19:00:56\",    \"Location\" : \"无锡市\"  }, {    \"Action\" : \"2\",    \"AcceptStation\" : \"【江苏省无锡市锡新开发区公司】 已收件 取件人: 杨军卫 (15267490788)\",    \"AcceptTime\" : \"2020-11-01 19:47:09\",    \"Location\" : \"无锡市\"  }, {    \"Action\" : \"2\",    \"AcceptStation\" : \"【江苏省无锡市锡新开发区】 已发出 下一站 【无锡转运中心公司】\",    \"AcceptTime\" : \"2020-11-01 19:47:19\",    \"Location\" : \"无锡市\"  }, {    \"Action\" : \"2\",    \"AcceptStation\" : \"【无锡转运中心公司】 已收入\",    \"AcceptTime\" : \"2020-11-02 06:24:31\",    \"Location\" : \"无锡市\"  }, {    \"Action\" : \"2\",    \"AcceptStation\" : \"【无锡转运中心公司】 已打包\",    \"AcceptTime\" : \"2020-11-02 06:52:21\",    \"Location\" : \"无锡市\"  }, {    \"Action\" : \"2\",    \"AcceptStation\" : \"【无锡转运中心】 已发出 下一站 【南京转运中心公司】\",    \"AcceptTime\" : \"2020-11-02 07:02:00\",    \"Location\" : \"无锡市\"  }, {    \"Action\" : \"2\",    \"AcceptStation\" : \"南京转运中心 已收入\",    \"AcceptTime\" : \"2020-11-02 13:20:04\",    \"Location\" : \"南京市\"  }, {    \"Action\" : \"2\",    \"AcceptStation\" : \"南京转运中心 已发出 下一站  江苏省南京市禄口机场\",    \"AcceptTime\" : \"2020-11-02 13:22:27\",    \"Location\" : \"南京市\"  }, {    \"Action\" : \"2\",    \"AcceptStation\" : \"南京转运中心 已收入\",    \"AcceptTime\" : \"2020-11-02 13:25:38\",    \"Location\" : \"南京市\"  } ],  \"State\" : \"2\",  \"EBusinessID\" : \"1683289\",  \"Success\" : true,  \"Location\" : \"南京市\"}";
        //String result = getOrderTracesByJson(expCode, expNo);
        ObjectMapper objMap = new ObjectMapper();
        try {
            ExpressInfoV1 ei = objMap.readValue(result, ExpressInfoV1.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Json方式 查询订单物流轨迹
     *
     * @throws Exception
     */
    private String getOrderTracesByJson(String expCode, String expNo) throws Exception {
        if (!properties.isEnable()) {
            return null;
        }

        String requestData = "{'OrderCode':'','ShipperCode':'" + expCode + "','LogisticCode':'" + expNo + "'}";

        Map<String, String> params = new HashMap<String, String>();
        params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));
        params.put("EBusinessID", properties.getAppId());
        params.put("RequestType", "8002");
        String dataSign = encrypt(requestData, properties.getAppKey(), "UTF-8");
        params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));
        params.put("DataType", "2");

        String result = HttpUtil.sendPost(ReqURL, params);
        System.out.println("查询订单物流轨迹,result: " + JSON.toJSONString(result));
        // 根据公司业务处理返回的信息......

        return result;
    }

    /**
     * MD5加密
     *
     * @param str     内容
     * @param charset 编码方式
     * @throws Exception
     */
    private String MD5(String str, String charset) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str.getBytes(charset));
        byte[] result = md.digest();
        StringBuffer sb = new StringBuffer(32);
        for (int i = 0; i < result.length; i++) {
            int val = result[i] & 0xff;
            if (val <= 0xf) {
                sb.append("0");
            }
            sb.append(Integer.toHexString(val));
        }
        return sb.toString().toLowerCase();
    }

    /**
     * Sign签名生成
     *
     * @param content  内容
     * @param keyValue Appkey
     * @param charset  编码方式
     * @return DataSign签名
     */
    private String encrypt(String content, String keyValue, String charset) {
        if (keyValue != null) {
            content = content + keyValue;
        }
        byte[] src = new byte[0];
        try {
            src = MD5(content, charset).getBytes(charset);
            return Base64Utils.encodeToString(src);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

}
